/**
 * @file ui_framework.c
 * @author taylor peng
 * @brief 
 * @version 0.1
 * @date 2021-12-12
 * 
 * @copyright Copyright (c) 2021
 * 
 */
#include <stdbool.h>
#include "ui_framework.h"
#include "traditional_menu.h"
#include "event.h"
#include "Bezier.h"
#include "display.h"
#include "bitmap.h"
#include "rotary_button.h"

/**  */
const char* TipName = "文件系统错误：请上报";

#define Smooth_Animation_Num    (sizeof(Menu_Smooth_Animation) / sizeof(Menu_Smooth_Animation[0]))
SMOOTH_ANIMATION_S Menu_Smooth_Animation[] = {
    /***********************************************************************
     * filter_val   last_val    target_val  smooth_weight   add_flag    b
     **********************************************************************/
    {0,             0,          0,          0.4,            1,          0}, //菜单项目滚动动画
    {0,             0,          0,          0.15,           1,          0}, //滚动条平滑动画
    {0,             0,          0,          0.15,           1,          0}, //菜单选项条长度平滑动画
    {0,             0,          0,          0.2,            0,          0}, //项目归位动画
};

/*复选框选中 10*10*/
const unsigned char CheckBoxSelection[] =
{
    0xff, 0xc0, 0x80, 0x40, 0x80, 0xc0, 0x81, 0xc0, 0x81, 0xc0, 0x83, 0x40, 0x9b,
    0x40, 0x8e, 0x40, 0x86, 0x40, 0xff, 0xc0
};

extern unsigned char* Switch_space[];

static inline void Draw_AppIcon(int x, int y, unsigned char *bitmap);
static inline void Draw_Slow_Bitmap_Resize(int x, int y, unsigned char* bitmap, int w1, int h1, int w2, int h2);
static inline void Draw_Box(int x, int y, int w, int h);
static inline void Draw_RBox(int x, int y, int w, int h, int r);
static inline void Draw_Framework(int x, int y, int w, int h);
static inline void Draw_Slow_Bitmap(int x, int y, const unsigned char* bitmap, unsigned char w, unsigned char h);

/**
 * @brief 获取数值长度，如：100， 长度为3
 * 
 */
static inline int Get_Dec_Deep(int x)
{
    int i = 0;
    do
    {
        i++;
        x /= 10;
    } while (x != 0);
    return i;
}

/**
 * @brief 绘制清屏
 * 
 */
static inline void Draw_Clear(void)
{
    Display_Clear();
}

/**
 * @brief 绘制显示
 * 
 */
static inline void Draw_Display(void)
{
    Display();
    Display_RefreshTickSet();
}

/**
 * @brief 抖动
 * 
 * @param sx 
 * @param sy 
 * @param ex 
 * @param ey 
 * @param f 
 * @param delayMs 
 */
void Blur(int sx, int sy, int ex, int ey, int f, int delayMs)
{
    for (int i = 0; i < f; i++)
    {
        for (int y = 0; y < ey; y++)
        {
            for (int x = 0; x < ex; x++)
            {
                if (x % 2 == y % 2 && x % 2 == 0 && x >= sx && x <= ex && y >= sy && y <= ey)
                {
                    Display_Pixel(x + (i > 0 && i < 3), y + (i > 1));
                }
            }
        }
        if (delayMs)
        {
            Draw_Display();
            delay(delayMs);
        }
    }
}

static unsigned int Get_UTF8_Ascii_Pix_Len(unsigned char size, char* s)
{
    return Disp.getUTF8Width(s);
}

static inline void Draw_Utf(int x, int y, char* s)
{
    Display_Utf(x, y + 1, s);
}

/**
 * @brief 绘制图形控件
 * 
 */
static inline void Draw_GraphicalControl(int x, int y, const char *str)
{
    Display_Utf(x, y + 1, str);
}

/**
 * @brief 绘制目录树
 * 
 */
static inline void Draw_DirectoryTree(int index, short option_id)
{
    char *str;
    short x_pos, y_pos;
    char tmp = 0;

    if (Menu_GetOperation(option_id) != OP_JUMP2MENU_TITLE)
    {
        // 可不予理会，此处目的是为了在文本前加上‘+’或者‘-’
        if (Menu_GetOperation(option_id) == OP_JUMP2MENU)
        {
            str = (char*)"+";
        }
        else
        {
            str = (char*)"-";
        }

        x_pos = 0;
        if (index != -1)
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        y_pos = (1 - Menu_GetSmoothAnimationFilterVal(3) * tmp) * ((index + Menu_GetSmoothAnimationFilterVal(0)) * 16 + 1);

        /**
         * @brief 调用显示函数，在目录前加入‘+’或者‘-’
         * 
         */
        Display_Utf(x_pos, y_pos, str);
    }
}

/**
 * @brief 绘制目录名（如果为文本菜单，则需要先调用Draw_DirectoryTree）
 * 
 */
static inline void Draw_DirectoryName(int index, short option_id)
{
    unsigned char tree_flag = 0;  // 目录树标志
    char *str;
    short x_pos, y_pos;
    char tmp = 0;

    if (Menu_GetOperation(option_id) != OP_JUMP2MENU_TITLE)
    {
        tree_flag = 1;
    }

    x_pos = X_POS_OFFSET * tree_flag;
    if (index != -1)
    {
        tmp = 1;
    }
    else
    {
        tmp = 0;
    }
    y_pos = (1 - Menu_GetSmoothAnimationFilterVal(3) * tmp) * ((index + Menu_GetSmoothAnimationFilterVal(0)) * 16 + 1);
    str = (char *)Menu_GetOptionName(option_id);

    /**
     * @brief 调用显示函数，此处 +1 猜测是为了留给选项条
     * 
     */
    Display_Utf(x_pos, y_pos + 1, str);
}

/**
 * @brief 绘制开关控件
 * 
 */
static inline void Draw_Switch(int index, short option_id)
{
    char *str;
    short x_pos, y_pos;
    x_pos = SCREEN_COLUMN - 32 - 1;
    y_pos = (index + Menu_GetSmoothAnimationFilterVal(0)) * 16 + 1;
    unsigned char addtional_para = Menu_GetAddtionalPara1(option_id);
    switch (addtional_para)
    {
    case SwitchControl_SmoothAnimation:
        if (Menu_Switch_GetSmoothAnimation())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_OptionStripFixedLength:
        if (Menu_Switch_GetOptionLength())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_PIDMode:
        if (Menu_Switch_GetPidMode())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_KFP:
        if (Menu_Switch_GetKfp())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_PanelSettings:
        if (Menu_Switch_GetPanel())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_ScreenFlip:
        if (Menu_Switch_GetFlip())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_Volume:
        if (Menu_Switch_GetVolume())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_RotaryDirection:
        if (Menu_GetEncoderRotaryDirection())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_HandleTrigger:
        if (Menu_Switch_GetHandleTrigger())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_Language:
        if (Menu_Switch_GetLanguage())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_TipID:
        if (Menu_Switch_GetTipId())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_BLE_State:
        if (Menu_Switch_GetBLE())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    case SwitchControl_MenuListMode:
        if (Menu_Switch_GetListMode())
        {
            str = (char*)"开启";
        }
        else
        {
            str = (char*)"关闭";
        }
        break;

    default:
        break;
    }
    Draw_GraphicalControl(x_pos, y_pos, str);
}

/**
 * @brief 绘制滑动条
 * 
 */
static inline void Draw_ProgessBar(int index, short option_id)
{
    char buffer[20];
    short x_pos, y_pos;
    unsigned char addtional_para = Menu_GetAddtionalPara1(option_id);

    switch (addtional_para)
    {
    case CScroll_Bar_ScreenBrightness:
    case CScroll_Bar_Scroll:
    case CScroll_Bar_BootTemp:
    case CScroll_Bar_SleepTemp:
    case CScroll_Bar_BoostTemp:
    case CScroll_Bar_ShutdownTime:
    case CScroll_Bar_SleepTime:
    case CScroll_Bar_BoostTime:
    case CScroll_Bar_ScreenProtectorTime:
    case CScroll_Bar_UndervoltageAlert:
    case CScroll_Bar_PID_AP:
    case CScroll_Bar_PID_AI:
    case CScroll_Bar_PID_AD:
    case CScroll_Bar_PID_CP:
    case CScroll_Bar_PID_CI:
    case CScroll_Bar_PID_CD:
    case CScroll_Bar_KFP_Q:
    case CScroll_Bar_KFP_R:
    case CScroll_Bar_SamplingRatioWork:
    case CScroll_Bar_ADC_PID_Cycle_List_0:
    case CScroll_Bar_ADC_PID_Cycle_List_1:
    case CScroll_Bar_ADC_PID_Cycle_List_2:
        sprintf(buffer, "%.2f", Menu_GetCScrollBarValue(addtional_para));
        break;

    default:
        return;
    }

    x_pos = SCREEN_COLUMN - 9 - Display_GetWidth(buffer);
    y_pos = (int)(index + Menu_GetSmoothAnimationFilterVal(0)) * 16;
    Draw_GraphicalControl(x_pos, y_pos, buffer);
}

/**
 * @brief 绘制单选框
 * 
 */
static inline void Draw_CheckBox(int index, short option_id)
{
    short x_pos, y_pos, w_pos, h_pos;
    unsigned char addtion_para = Menu_GetAddtionalPara1(option_id);
    unsigned char state = 0;
    switch (addtion_para)
    {
    case SwitchControl_SmoothAnimation:
        state = Menu_Switch_GetSmoothAnimation();
        break;

    case SwitchControl_OptionStripFixedLength:
        state = Menu_Switch_GetOptionLength();
        break;

    case SwitchControl_PIDMode:
        state = Menu_Switch_GetPidMode();
        break;

    case SwitchControl_KFP:
        state = Menu_Switch_GetKfp();
        break;

    case SwitchControl_PanelSettings:
        state = Menu_Switch_GetPanel();
        break;

    case SwitchControl_ScreenFlip:
        state = Menu_Switch_GetFlip();
        break;

    case SwitchControl_Volume:
        state = Menu_Switch_GetVolume();
        break;

    case SwitchControl_RotaryDirection:
        state = Menu_GetEncoderRotaryDirection();
        break;

    case SwitchControl_HandleTrigger:
        state = Menu_Switch_GetHandleTrigger();
        break;

    case SwitchControl_Language:
        state = Menu_Switch_GetLanguage();
        break;

    case SwitchControl_TipID:
        state = Menu_Switch_GetTipId();
        break;

    case SwitchControl_BLE_State:
        state = Menu_Switch_GetBLE();
        break;

    case SwitchControl_MenuListMode:
        state = Menu_Switch_GetListMode();
        break;

    default:
        break;
    }

    if (state == Menu_GetAddtionalPara2(option_id))
    {
        x_pos = SCREEN_COLUMN - 32 - 1 + 15;
        y_pos = (index + Menu_GetSmoothAnimationFilterVal(0)) * 16 + 2;
        w_pos = 10;
        h_pos = 10;
        Draw_Slow_Bitmap(x_pos, y_pos, CheckBoxSelection, w_pos, h_pos);
    }
    else
    {
        x_pos = SCREEN_COLUMN - 32 - 1 + 15;
        y_pos = (index + Menu_GetSmoothAnimationFilterVal(0)) * 16 + 2;
        w_pos = 10;
        h_pos = 10;
        Draw_Framework(x_pos, y_pos, w_pos, h_pos);
    }

    //当前项高亮
    if ((int)Menu_GetCScrollBarValue(CScroll_Bar_Scroll) == index)
    {
        Display_SetColor(2);
        x_pos = SCREEN_COLUMN - 32 - 2 + 15;
        y_pos = (index + Menu_GetSmoothAnimationFilterVal(0)) * 16 + 1;
        w_pos = 12;
        h_pos = 12;
        Draw_Box(x_pos, y_pos, w_pos, h_pos);
        Display_SetColor(1);
    }
}

/**
 * @brief 对特殊菜单控件的分类渲染
 * 
 */
static inline void Draw_Special(int index, short option_id)
{
    switch (Menu_GetOperation(option_id))
    {
    //开关控件
    case OP_SWITCH:
        Draw_Switch(index, option_id);
        break;

    //滑动条
    case OP_PROGRESS_BAR:
        Draw_ProgessBar(index, option_id);
        break;

    //单选框
    case OP_SINGLE_BOX:
        Draw_CheckBox(index, option_id);
        break;

    default:
        break;
    }
}

/**
 * @brief 绘制空心方形
 * 
 * @param x 
 * @param y 
 * @param w 
 * @param h 
 */
static inline void Draw_Box(int x, int y, int w, int h)
{
    Display_Box(x, y, w, h);
}

static inline void Draw_RBox(int x, int y, int w, int h, int r)
{
    Display_RBox(x, y, w, h, r);
}

/**
 * @brief 绘制实心方形
 * 
 */
static inline void Draw_Framework(int x, int y, int w, int h)
{
    Display_Framework(x, y, w, h);
}

/**
 * @brief 绘制滚动条
 * 
 */
static inline void Draw_ScrollBar(int x, int y, int w, int h, int s, int v)
{
    Display_SetColor(1);
    if (w < h)
    {
        Display_VLine(x + w / 2.0, y, h);
        if (s < h && h / s >= 4)
            for (int i = 0; i < s + 1; i++)
            {
                if (i % 2)
                    Display_HLine(x + w / (float)s, y + (h / (float)s) * i, w / 2.0 + 1);
                else
                    Display_HLine(x, y + (h / (float)s) * i, w);
            }
        if (s > h)
            s = h;
        Draw_Box(x, v, w, h / (float)s);
    }
    else
    {
        Display_HLine(x, y + h / 2.0, w);
        if (s < h && h / s >= 4)
            for (int i = 0; i < s + 1; i++)
            {
                if (i % 2)
                    Display_VLine(x + (w / (float)s) * i, y + (h / (float)s), h / 2.0 + 1);
                else
                    Display_VLine(x + (w / (float)s) * i, y, h);
            }
        if (s > w)
            s = w;
        Draw_Box(v, y, w / (float)s, w);
    }
}

/**
 * @brief 绘制滚动条
 * 
 */
static inline void Draw_RollingStrip(short level_id)
{
    short x_pos, y_pos, w_pos, h_pos, v_pos, s_pos;
    x_pos = SCREEN_COLUMN - ROLLING_STRIP_WIDTH;
    y_pos = 0;
    w_pos = ROLLING_STRIP_WIDTH;
    h_pos = SCREEN_ROW - 1;
    /** s_pos 获取当前层菜单包含的所有选项条目 */
    s_pos = Menu_GetCurMaxId(level_id) + 1;
    /** map为映射函数，将旧值映射到新值，请参见网上说明 */
    v_pos = map(Menu_GetCurOptId(level_id) + Menu_GetCScrollBarValue(CScroll_Bar_Scroll),
                0,
                Menu_GetCurMaxId(level_id) + 1,
                -Menu_GetSmoothAnimationFilterVal(0) * (SCREEN_ROW / (Menu_GetCurMaxId(level_id) + 1)),
                SCREEN_ROW - 1);
    Draw_ScrollBar(x_pos, y_pos, w_pos, h_pos, s_pos, v_pos);
}

/**
 * @brief 绘制数值条
 * 
 * @param tar_val 目标值
 * @param min_val 目标值的最小值
 * @param max_val 目标值的最大值
 * @param x_pos 左上顶点x轴坐标
 * @param y_pos 左上顶点y轴坐标
 * @param width 
 * @param height 
 * @param color 
 */
static inline void Draw_NumBar(float tar_val, float min_val, float max_val, int x_pos, int y_pos, int width, int height, int color)
{
    char buffer[20];
    sprintf(buffer, "%.2f", tar_val);
    unsigned char textWidth = Display_GetWidth(buffer) + 3;

    Display_SetColor(color);
    Draw_Framework(x_pos, y_pos, width - textWidth - 2, height);
    Draw_Box(x_pos + 2, y_pos + 2, map(tar_val, min_val, max_val, 0, width - textWidth - 6), height - 4);

    Display_String(x_pos + width - textWidth, y_pos - 1, buffer);
    //进行去棱角操作:增强文字视觉焦点
    Display_SetColor(0);
    Display_SetColor(1);
}

/**
 * @brief 自适应屏幕右下角角标绘制
 * 
 */
static inline void Draw_PageCornerMark(short level_id)
{
    int numerator = Menu_GetCurOptId(level_id) + 1 + (int)Menu_GetCScrollBarValue(CScroll_Bar_Scroll);
    int denominator = Menu_GetCurMaxId(level_id) + 1;
    char buffer[20];
    char w = (Get_Dec_Deep(numerator) + Get_Dec_Deep(denominator) + 3) * 6;
    char x = SCREEN_COLUMN - 8 - w;
    char y = SCREEN_ROW - 12;

    if (millis() < PagesCornerTipEvent_Get() + pages_Tip_Display_Timeout)
    {
        //绘制白色底色块
        Display_SetColor(1);
        Draw_RBox(x + 1, y - 1, w, 13, 1);
        //绘制下标文字
        Display_SetColor(0);
        Display_Cursor(x, y + 1);
        sprintf(buffer, "[%d/%d]", numerator, denominator);
        Display_Print(buffer);
    }
    //恢复颜色设置
    Display_SetColor(1);
}

/**
 * @brief 绘制反色高亮被选项
 * 
 */
static inline void Draw_ColorHighlight(short level_id)
{
    short x_pos, y_pos, w_pos, h_pos, radius;
    short option_id = Menu_GetOptionId(Menu_GetCurLevelId(level_id), Menu_GetCurOptId(level_id) + (unsigned short)Menu_GetCScrollBarValue(CScroll_Bar_Scroll));
    Display_SetColor(2);
    x_pos = 0;
    y_pos = ((short)Menu_GetCScrollBarValue(CScroll_Bar_Scroll) - Menu_GetSmoothAnimationFilterVal(1)) * 16;
    if (Menu_Switch_GetOptionLength())
    {
        /** 文本固定长度 */
        w_pos = TEXT_FIXED_LENGTH;
    }
    else
    {
        /** 文本自适应长度 */
        unsigned short text_length = Display_GetWidth((char *)Menu_GetOptionName(option_id));
        unsigned char tmp;
        if (Menu_GetOperation(option_id) != OP_JUMP2MENU_TITLE)
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        w_pos = text_length - Menu_GetSmoothAnimationFilterVal(2) + 12 * tmp + 1;
    }
    h_pos = CNSize + 2;
    radius = 0;
    Display_RBox(x_pos, y_pos, w_pos, h_pos, radius);
    Display_SetColor(1);
}

/**
 * @brief 绘制项目滚动处理
 * 
 */
static inline void Draw_ItemScroll(short level_id)
{
    Menu_SetCScrollBarValue(CScroll_Bar_Scroll, (float)(sys_Counter_Get() - 1));
    if ((int)Menu_GetCScrollBarValue(CScroll_Bar_Scroll) >= (int)Menu_GetCScrollBarMaxValue(CScroll_Bar_Scroll))
    {
        // Log(LOG_INFO, "尝试往下滚动");
        printf("尝试往下滚动\r\n");
        // MenuLevel[level_id].cur_opt_id++;
        stActive_Menu.active_menu_level_id++;
        sys_Counter_SetVal((int)Menu_GetCScrollBarMaxValue(CScroll_Bar_Scroll));
    }
    else if ((int)Menu_GetCScrollBarValue(CScroll_Bar_Scroll) <= -1)
    {
        // Log(LOG_INFO, "尝试往上滚动");
        printf("尝试往上滚动\r\n");
        // MenuLevel[level_id].cur_opt_id--;
        stActive_Menu.active_menu_level_id--;
        sys_Counter_SetVal(1);
    }
}

/**
 * @brief 编码器控制页内选择框滚动选择
 * 
 */
static inline void Draw_SelectBox(short level_id)
{
    unsigned short val = constrain((int)Menu_GetCScrollBarValue(CScroll_Bar_Scroll), 0, (int)Menu_GetCScrollBarMaxValue(CScroll_Bar_Scroll) - 1);
    Menu_SetCScrollBarValue(CScroll_Bar_Scroll, (float)val);

    short option_id = constrain(Menu_GetCurOptId(level_id),
                                   Menu_GetCurMinId(level_id),
                                   (Menu_GetCurMaxId(level_id) > Menu_GetCScrollBarMaxValue(CScroll_Bar_Scroll) - 1) ?
                                   (Menu_GetCurMaxId(level_id) - Menu_GetCScrollBarMaxValue(CScroll_Bar_Scroll) - 1) : 0);
    Menu_SetCurOptId(level_id, option_id);
}

/**
 * @brief 更新过渡动画
 * 
 */
static inline void Draw_TransitionAnimations(short level_id)
{
    short option_id = Menu_GetOptionId(Menu_GetCurLevelId(level_id), Menu_GetCurOptId(level_id) + (int)Menu_GetCScrollBarValue(CScroll_Bar_Scroll));

    Menu_SetSmoothAnimationTargetVal(0, Menu_GetCurOptId(level_id));
    Menu_SetSmoothAnimationTargetVal(1, Menu_GetCurOptId(level_id) + (int)Menu_GetCScrollBarValue(CScroll_Bar_Scroll));
    Menu_SetSmoothAnimationTargetVal(2, Get_UTF8_Ascii_Pix_Len(1, (char *)Menu_GetOptionName(level_id)));
}

/**
 * @brief 绘制选项名称
 * 
 */
static inline void Draw_OptionName(int x, int y, const char *str)
{
    /**
     * @brief 调用显示函数
     * 
     */
    Display_Utf(x, y + 1, str);
}

/**
 * @brief 居中显示项目名
 * 
 */
static inline void Draw_TextCenter(short level_id)
{
    // int opt_id = Menu_GetOptionId(Menu_GetCurLevelId(level_id), Menu_GetCurOptId(level_id));
    // char *str = Menu_GetOptionName(opt_id);
    // short x_pos = UTF8_HMiddle(0, 128, 1, str);
    // short y_pos = 50;
    // Draw_OptionName(x_pos, y_pos, str);
}

/**
 * @brief 绘制APP图标
 * 
 */
static inline void Draw_AppIcon(int x, int y, unsigned char *bitmap)
{
    /**
     * @brief 调用显示函数
     * 
     */
    Display_SetColor(1);
    Display_RBox(x - 3, y - 3, 42 + 6, 42 + 6, 4);
    Display_SetColor(0);

    Display_SetColor(1);
    Draw_Slow_Bitmap_Resize(x, y, bitmap + 1, bitmap[0], bitmap[0], 42, 42);
}

/**
 * @brief 菜单图标
 * 
 */
static inline void Draw_Icon(short level_id)
{
    int option_id;
    int id = Menu_GetOptionId(Menu_GetCurLevelId(level_id), Menu_GetCurOptId(level_id));
    short x_pos, y_pos;
    unsigned char *str;
    for (unsigned char i = 0; i < 5; i++)
    {
        option_id = Menu_GetOptionId(Menu_GetCurLevelId(level_id), Menu_GetCurOptId(level_id) + i - 2);

        if (((Menu_GetCurOptId(level_id) - 2 + i) >= 0) &&
            ((Menu_GetCurOptId(level_id) - 2 + i) <= Menu_GetCurMaxId(level_id)))
        {
            //绘制菜单项目图标
            if (Menu_GetOperation(id) != OP_JUMP2MENU_TITLE)
            {
                if (Menu_GetOperation(option_id) != OP_JUMP2MENU_TITLE)
                {
                    unsigned char tmp = 0;
                    if (i != -1)
                    {
                        tmp = 1;
                    }
                    else
                    {
                        tmp = 0;
                    }
                    x_pos = (1 - Menu_GetSmoothAnimationFilterVal(3) * tmp) * (-69 + i * 56 + Menu_GetSmoothAnimationFilterVal(0) * 56);
                    y_pos = 3;
                    str = Menu_GetIcon(option_id);
                    Draw_AppIcon(x_pos, y_pos, str);
                }
            }
        }
    }

    Menu_SetCurOptId(level_id, sys_Counter_Get());
    Menu_SetSmoothAnimationTargetVal(0, Menu_GetCurOptId(level_id));
}

/**
 * @brief 
 * 
 * @param x 
 * @param y 
 * @param bitmap 
 * @param w 
 * @param h 
 */
static inline void Draw_Slow_Bitmap(int x, int y, const unsigned char* bitmap, unsigned char w, unsigned char h)
{
    unsigned char color = Display_GetColor();
    int xi, yi, intWidth = (w + 7) / 8;
    for (yi = 0; yi < h; yi++)
    {
        for (xi = 0; xi < w; xi++)
        {
            if (pgm_read_byte(bitmap + yi * intWidth + xi / 8) & (128 >> (xi & 7)))
            {
                Display_Pixel(x + xi, y + yi);
            }
            else if (color != 2)
            {
                Display_SetColor(0);
                Display_Pixel(x + xi, y + yi);
                Display_SetColor(color);
            }
        }
    }
}

/**
 * @brief 绘制位图缩放
 * 
 */
static inline void Draw_Slow_Bitmap_Resize(int x, int y, unsigned char* bitmap, int w1, int h1, int w2, int h2)
{
    unsigned char color = Display_GetColor();
    float mw = (float)w2 / w1;
    float mh = (float)h2 / h1;
    unsigned char cmw = ceil(mw);
    unsigned char cmh = ceil(mh);
    int xi, yi, byteWidth = (w1 + 7) / 8;
    for (yi = 0; yi < h1; yi++)
    {
        for (xi = 0; xi < w1; xi++)
        {
            if (pgm_read_byte(bitmap + yi * byteWidth + xi / 8) & (1 << (7 - (xi & 7))))
            {
                Draw_Box(x + xi * mw, y + yi * mh, cmw, cmh);
            }
            else if (color != 2)
            {
                Display_SetColor(0);
                Draw_Box(x + xi * mw, y + yi * mh, cmw, cmh);
                Display_SetColor(color);
            }
        }
    }
}

static inline void Draw_Pixel_Resize(int x, int y, int ox, int oy, int w, int h)
{
    int xi = x - ox;
    int yi = y - oy;

    Draw_Box(ox + xi * w, oy + yi * h, w, h);
}

/**
 * @brief 绘制启动信息
 * 
 */
static inline void Draw_BootMsg(void)
{
    // Clear();

    // char buffer[50];

    // for (unsigned char i = 0; i < 5; i++)
    // {
    //     Display_Cursor(0, 12 * i + 1);

    //     switch (i)
    //     {
    //     case 0:
    //         sprintf(buffer, "[启动信息] 编译时间");
    //         break;
    //     case 1:
    //         sprintf(buffer, "%s %s", __DATE__, __TIME__);
    //         break;
    //     case 2:
    //         sprintf(buffer, "MAC %s", Mac_GetString());
    //         break;
    //     case 3:
    //         sprintf(buffer, "CPU频率:%u MHZ", Cpu_GetFreq());
    //         break;
    //     case 4:
    //         sprintf(buffer, "%s", Version_Get());
    //         break;
    //     }
    //     Display_Print(buffer);
    // }
    // Draw_Display();
    // delay(300);
}

/**
 * @brief 绘制屏保-密集运算线条
 * 
 */
static inline void DrawIntensiveComputingLine(void)
{
    static unsigned char Line[4];
    for (unsigned char a = 0; a < 4; a++)
    {
        Line[a] += rand() % 2 - 1;
        if (Line[a] > 128) Line[a] -= 128;
        for (unsigned char b = 0; b < rand() % 3 + 3; b++)
        {
            Display_HLine(0, Line[a] + rand() % 20 - 10, 128); //水平线
            Display_VLine(Line[a] + rand() % 20 - 10, 0, 64); //垂直线
        }
    }
}

/**
 * @brief 密集运算屏保
 * 
 */
void DrawIntensiveComputing(void)
{
    float calculate;

    //随机线条
    DrawIntensiveComputingLine();

    calculate = sin(millis() / 4000.0);
    //模拟噪点
    for (int i = 0; i < calculate * 256 + 256; i++)
    {
        Display_Pixel(rand() % 128, rand() % 64);
    }
}

/**
 * @brief 在屏幕中心绘制文本
 * 
 */
static inline void Draw_MsgInCenter(char *str)
{
    int w = Get_UTF8_Ascii_Pix_Len(1, str) + 2;
    int h = 12;
    int x = (SCREEN_COLUMN - w) / 2;
    int y = (SCREEN_ROW - h) / 2;

    Display_SetColor(0);

    Display_SetColor(0);
    Blur(0, 0, SCREEN_COLUMN, SCREEN_ROW, 3, 0);
    Draw_Framework(x - 1, y - 3, w + 1, h + 3);
    Display_SetColor(1);
    Draw_RBox(x, y - 2, w, h + 2, 2);
    Display_SetColor(0);
    Draw_Utf(x + 1, y - 1, str);
    Display_SetColor(1);
}

/**
 * @brief 绘制高亮文本
 * 
 * @param x 
 * @param y 
 * @param s 
 */
void DrawHighLightText(int x, int y, char *s)
{
    int TextWidth = Display_GetWidth(s);
    int TextHigh = Display_GetMaxCharHeight();
    unsigned char color = Display_GetColor();

    if (color == 2)
    {
        Display_Utf(x + 1, y + 2, s);
        Display_RBox(x, y, TextWidth + 2, TextHigh, 3);
    }
    else
    {
        Display_RBox(x, y, TextWidth + 2, TextHigh, 3);
        Display_SetColor(!color);
        Display_Utf(x + 1, y + 2, s);
        Display_SetColor(color);
    }
}

/**
 * @brief 绘制温度状态条
 * 
 * @param color 
 */
void DrawStatusBar(bool color)
{
    Display_SetColor(color);
    //温度条
    //框
    Display_Framework(0, 53, 103, 11);
    //条
    if (TemperatureRealityEvent_Get() <= TipMaxTemp)
        Display_Box(0, 53, map(TemperatureRealityEvent_Get(), TipMinTemp, TipMaxTemp, 5, 98), 11);

    //功率条
    Draw_Framework(104, 53, 23, 11);
    Draw_Box(104, 53, map(Power_Get(), 0, 255, 0, 23), 11);

    Display_HLine(117, 51, 11);
    Display_Pixel(103, 52);
    Display_Pixel(127, 52);

    //////////////进入反色////////////////////////////////
    Display_SetColor(2);

    //画指示针
    Draw_Slow_Bitmap(map(TemperatureVirtualEvent_Get(), TipMinTemp, TipMaxTemp, 5, 98) - 4,
                     54,
                     PositioningCursor,
                     8,
                     8);

    Display_Cursor(2, 53);
    // Display_Printf("%.0f", TemperatureVirtualEvent_Get());

    Display_Cursor(105, 53);
    // Display_Printf("%d%%", map(Power_Get(), 0, 255, 0, 100));
    Display_SetColor(color);
}

/**
 * @brief 短文本编辑器
 * 
 * @param title 
 * @param text 
 */
void TextEditor(char *title, char *text)
{
}

/**
 * @brief 快速打开烙铁列表
 * 
 */
static inline void Fast_OpenSolerTipList(void)
{
    printf("尝试打开烙铁头列表\n");
    //关闭功率管输出
    // SetPOWER(0);
    //初始化菜单
    FlashTipMenu(); //刷新菜单系统烙铁列表

    Menu_SetJumpAndExit(true);    //菜单标志：“跳转即退出” 在设置完Tip后自动退出菜单
    Menu_SetJumpAndExit_Level(2); //当菜单进行跳转操作，跳转到该 Menu_JumpAndExit_Level 层后检查“跳转即退出” 标志

    Menu_SetCurOptId(MENU_LEVEL_15, OPTION_ID_0);             //复位第一层菜单的位置
    stActive_Menu.active_menu_level_id = MENU_LEVEL_15;       //设定跳转目标
    Menu_SetCScrollBarValue(CScroll_Bar_Scroll, OPTION_ID_0); //复位第一层菜单的位置
    Menu_Enter();
}

/**
 * @brief 快速打开PID菜单
 * 
 */
static inline void Fast_OpenPIDList(void)
{
    //关闭功率管输出
    // SetPOWER(0);
    //初始化菜单
    FlashTipMenu(); //刷新菜单系统烙铁列表

    Menu_SetJumpAndExit(true);    //菜单标志：“跳转即退出” 在设置完Tip后自动退出菜单
    Menu_SetJumpAndExit_Level(2); //当菜单进行跳转操作，跳转到该 Menu_JumpAndExit_Level 层后检查“跳转即退出” 标志

    Menu_SetCurOptId(MENU_LEVEL_16, OPTION_ID_0); //复位第一层菜单的位置
    stActive_Menu.active_menu_level_id = MENU_LEVEL_16; //设定跳转目标
    Menu_SetCScrollBarValue(CScroll_Bar_Scroll, OPTION_ID_0); //复位第一层菜单的位置
    Menu_Enter();
}

/**
 * @brief 退出菜单并保存
 * 
 */
void Draw_MenuExitSave(void)
{
    //过渡离开
    Display_SetColor(0);
    Blur(0, 0, SCREEN_COLUMN, SCREEN_ROW, 4, 66 * Menu_Switch_GetSmoothAnimation());
    Display_SetColor(1);

    //保存配置
    // SYS_Save();

    Menu_Exit();
}

/**
 * @brief 系统UI
 * 
 */
unsigned char* C_table[] = {c1, c2, c3, Lightning, c5, c6, c7};
void System_UI(void)
{
    /** 清除缓存 */
    Draw_Clear();

    /** 进入菜单 */
    if (MenuOpen_GetState())
    {
        Render_Menu();
    }
    /** 未开启菜单 */
    else
    {
        /**
         * @brief 可以有屏保，各类动作刷新
         * 
         */
        //睡眠模式屏保入口
        if (Sleep_GetEvent() && SleepScreenProtect_Get())
        {
            RunSleepLoop();
        }
        else
        {
            //显示烙铁头名称
            Display_Utf(0, 1, TipName);

            //温度控制状态图标
            Draw_Slow_Bitmap(74, 37, C_table[TemperatureCtrlEvent_Get()], 14, 14);

            //显示中文状态信息
            Display_Utf(91, 40, TempCTRL_Status_Mes[TemperatureCtrlEvent_Get()]);

            //欠压警报
            if (UnderVoltage_Get())
            {
                if ((millis() / 1000) % 2)
                {
                    //欠压告警图标
                    Draw_Slow_Bitmap(74, 21, Battery_NoPower, 14, 14);
                }
                else
                {
                    //主电源电压
                    Display_Cursor(74, 24);
                    // Display_Printf("%.1fV", Get_MainPowerVoltage());
                }
            }
            else
            {
                //显示蓝牙图标
                if (BluetoothEvent_Get())
                {
                    Draw_Slow_Bitmap(92, 25, IMG_BLE_S, 9, 11);
                }
            }

            //显示当前温度
            Display_Font(LOGISOSO38_TR);
            Display_Cursor(0, 12);

            if (TemperatureCtrlEvent_Get() == TEMP_STATUS_ERROR)
            {
                if ((millis() / 250) % 2)
                {
                    Display_Print("---");
                }
            }
            else
            {
                //如果温度波动足够小，则显示当前温度为设定温度
                if (TemperatureDiffEvent_Get() < 10)
                {
                    // Display_Printf("%.0lf", TemperatureVirtualEvent_Get()); //显示"假"温度(设定温度)
                }
                else
                {
                    // Display_Printf("%.0lf", TemperatureRealityEvent_Get()); //显示真实温度2
                }
            }

            Display_Font(WQY12_T_GB2312);

            //右上角运行指示角标
            // if (POWER > 0 && PWM_WORKY)
            // {
            //     unsigned char TriangleSize = map(POWER, 0, 255, 16, 0);
            //     Display_Triangle((119 - 12) + TriangleSize, 12, 125, 12, 125, (18 + 12) - TriangleSize);
            // }

            /////////////////////////////////////绘制遮罩层//////////////////////////////////////////////
            Display_SetColor(2);
            //几何图形切割
            Display_Box(0, 12, 96, 40);
            Display_Triangle(96, 12, 96, 52, 125, 42);
            Display_Triangle(125, 42, 96, 52, 118, 52);
            Display_SetColor(1);

            //绘制底部状态条
            DrawStatusBar(1);

            //如果当前是处于爆发技能，则显示技能剩余时间进度条
            if ((TemperatureCtrlEvent_Get() == TEMP_STATUS_BOOST) && (Display_RefreshTickGet() % 2))
            {
                unsigned char BoostTimeBar = map(millis() - BoostTimer_Get(), 0, BoostDuringTime_Get() * 1000, 0, 14);
                Display_Box(74, 37, 14, BoostTimeBar);
            }
        }
        // 显示
        Draw_Display();
        //编码器长按按键进入菜单
        if (KeyEvent_Get() == EVT_LONG_PRESS)
        {
            //初始化菜单
            Menu_Init();
        }
    }
}

unsigned char ScreenFlip = 0;
unsigned char RotaryDirection = 0;
unsigned char MenuListMode = 0;

/**
 * @brief 更新屏幕亮度设置
 * 
 */
void Update_OLED_Light_Level(void)
{
    Display_SendF("c", 0x81);  //向SSD1306发送指令：设置内部电阻微调
    Display_SendF("c", (unsigned char)Menu_GetCScrollBarValue(CScroll_Bar_ScreenBrightness)); //微调范围（0-255）
}

/**
 * @brief 屏幕翻转显示
 * 
 */
void PopMsg_ScreenFlip(void)
{
    char buffer[20];
    sprintf(buffer, "%s", (ScreenFlip == true) ? "翻转显示" : "正常显示");
    Pop_Windows(buffer);
    delay(500);
}

/**
 * @brief 控制屏幕翻转
 * 
 */
void Update_OLED_Flip(void)
{
    if (MenuOpen_GetState())
    {
        PopMsg_ScreenFlip();
    }
}

/**
 * @brief 控制编码器方向
 * 
 */
void PopMsg_RotaryDirection(void)
{
    char buffer[20];
    sprintf(buffer, "编码器:%s", (Menu_GetEncoderRotaryDirection() == true) ? "顺时针" : "逆时针");
    Pop_Windows(buffer);
    delay(500);
}

/**
 * @brief 
 * 
 */
void PopMsg_ListMode(void)
{
    char buffer[20];
    sprintf(buffer, "%s", (Menu_Switch_GetListMode() == true) ? "列表模式" : "图标模式");
    Pop_Windows(buffer);
    delay(500);
    Menu_Enter();
}

/**
 * @brief 按照标题进行跳转 标题跳转 跳转标题
 * 
 */
void JumpWithTitle(void)
{
    Menu_DefaultRun(stActive_Menu.active_menu_level_id, 0);
}

/**
 * @brief 过渡动画运算
 * 
 */
void Smooth_Animation_System(void)
{
    for (unsigned char i = 0; i < Smooth_Animation_Num; i++)
    {
        //优化计算：变形过滤器
        if (Menu_GetSmoothAnimationFilterVal(i) && abs(Menu_GetSmoothAnimationFilterVal(i) * 100) < 1.5)
        {
            Menu_SetSmoothAnimationFilterVal(i, 0);
        }
        //动画控制变量是否需要更新
        if (Menu_GetSmoothAnimationLastVal(i) != Menu_GetSmoothAnimationTargetVal(i))
        {
            //是否允许累加
            if (Menu_GetSmoothAnimationAddFlag(i))
            {
                float tmp = Menu_GetSmoothAnimationFilterVal(i) + Menu_GetSmoothAnimationTargetVal(i) - Menu_GetSmoothAnimationLastVal(i);
                Menu_SetSmoothAnimationFilterVal(i, tmp);
            }
            else
            {
                Menu_SetSmoothAnimationFilterVal(i, Menu_GetSmoothAnimationTargetVal(i) - Menu_GetSmoothAnimationLastVal(i));
            }

            //重置标志
            Menu_SetSmoothAnimationLastVal(i, Menu_GetSmoothAnimationTargetVal(i));

            //动画特殊个性化配置
            switch (i)
            {
            default:
                break;
            }
        }
        //使用被选的动画计算函数计算动画
        switch (Menu_GetSmoothAnimationSmoothB(i))
        {
        case 0:
            float tmp = Menu_GetSmoothAnimationFilterVal(i) - Menu_GetSmoothAnimationFilterVal(i) * Menu_GetSmoothAnimationSmoothWeight(i);
            Menu_SetSmoothAnimationFilterVal(i, tmp);
            break;
        }
    }
}

/**
 * @brief 
 * 
 */
void SmoothAnimationSystem_Clean(void)
{
    for (unsigned char i = 0; i < Smooth_Animation_Num; i++)
    {
        Menu_Smooth_Animation[i].filter_val = 0;
    }
}

/**
 * @brief 文本浏览器
 * 
 */
void Text_Browser(char *str)
{
}

/**
 * @brief 菜单系统设置编码器
 * 
 */
void MenuSYS_SetCounter(void)
{
    if (!MenuOpen_GetState())
        return;
    printf("菜单系统设置编码器\n");
    if (/* !Menu_GetIconFlag(stActive_Menu.real_level_id) || */  Menu_Switch_GetListMode() || SCREEN_ROW <= 32)
    {
        //设置编码器滚动范围
        Menu_SetCurMinId(stActive_Menu.real_level_id, OPTION_ID_0);//重置选项最小值：从图标模式切换到列表模式会改变该值
        unsigned char tmp1 = (int)Menu_GetCScrollBarMinValue(CScroll_Bar_Scroll);
        unsigned char tmp2 = (int)Menu_GetCurMaxId(stActive_Menu.real_level_id);
        unsigned char MinimumScrolling;
        if (tmp1 < tmp2)
        {
            MinimumScrolling = tmp1;
        }
        else
        {
            MinimumScrolling = tmp2;
        }
        sys_Counter_Set((int)Menu_GetCScrollBarMinValue(CScroll_Bar_Scroll),
                        MinimumScrolling + 1,
                        1,
                        (int)Menu_GetCScrollBarValue(CScroll_Bar_Scroll) + 1); //+(1) 是因为实际上计算会-1 ,这里要补回来
    }
    else
    {
        printf("Menu_Enter:图标模式\n");
        unsigned short option_id = Menu_GetOptionId(stActive_Menu.real_level_id, OPTION_ID_0);
        if (Menu_GetOperation(option_id))
        {
            Menu_SetCurMinId(stActive_Menu.real_level_id, OPTION_ID_1);
        }

        sys_Counter_Set(Menu_GetCurMinId(stActive_Menu.real_level_id),
                        Menu_GetCurMaxId(stActive_Menu.real_level_id),
                        1,
                        Menu_GetCurOptId(stActive_Menu.real_level_id));
        Menu_SetCScrollBarValue(CScroll_Bar_Scroll, 0);
    }
}

/**
 * @brief 自适应文本大小信息弹窗
 * 
 */
void Pop_Windows(char* s)
{
    int w = Get_UTF8_Ascii_Pix_Len(1, s) + 2;
    int h = 12;
    int x = (SCREEN_COLUMN - w) / 2;
    int y = (SCREEN_ROW - h) / 2;

    Display_SetColor(0);
    Blur(0, 0, SCREEN_COLUMN, SCREEN_ROW, 3,
         66 * Menu_Switch_GetSmoothAnimation()); //<=15FPS以便人眼察觉细节变化

    int ix = 0;
    for (int i = 1; i <= 10; i++)
    {
        //震荡动画
        if (Menu_Switch_GetSmoothAnimation())
        {
            ix = (10 * cos((i * 3.14) / 2.0)) / i;
        }

        Display_SetColor(0);
        Blur(0, 0, SCREEN_COLUMN, SCREEN_ROW, 3, 0);
        Display_Framework(x - 1 + ix, y - 3, w + 1, h + 3);
        Display_SetColor(1);
        Display_RBox(x + ix, y - 2, w, h + 2, 2);
        Display_SetColor(0);
        Draw_Utf(x + 1 + ix, y - 1, s);
        Display_SetColor(1);
        Draw_Display();
        delay(20 * Menu_Switch_GetSmoothAnimation());
    }
}

/**
 * @brief 绘制APP
 * 
 */
void Draw_APP(int x, int y, unsigned char* bitmap)
{
    Display_SetColor(1);
    Display_RBox(x - 3, y - 3, 42 + 6, 42 + 6, 4);
    Display_SetColor(0);

    Display_SetColor(1);
    Draw_Slow_Bitmap_Resize(x, y, bitmap + 1, bitmap[0], bitmap[0], 42, 42);
}

/**
 * @brief 渲染主菜单
 * 
 */
void Render_Menu(void)
{
    if (!MenuOpen_GetState())
    {
        return;
    }
    // 清缓存
    Draw_Clear();

    // 计算过渡动画
    if (Menu_Switch_GetSmoothAnimation())
    {
        Smooth_Animation_System();
    }

    unsigned short tmp_level_id = Menu_GetLevelId(stActive_Menu.active_menu_level_id);
    unsigned short tmp_opt_id = Menu_GetOptionId(Menu_GetCurLevelId(tmp_level_id), Menu_GetCurOptId(tmp_level_id) + (OPTION_ID_E)Menu_GetCScrollBarValue(CScroll_Bar_Scroll));

    /**
     * @brief 若当前菜单层级没有开启图标化则使用普通文本菜单的模式进行渲染显示
     *        若屏幕分辨率低于128*32 则强制启用文本菜单模式
     */
    if (Menu_Switch_GetListMode() || SCREEN_ROW <= 32)
    {
        // 显示菜单项目名::这里有两行文字是在屏幕外 用于动过渡动画
        for (int i = -1; i < SCREEN_PAGE_NUM / 2 + 1; i++)
        {
            if (Menu_CheckOptionId(tmp_level_id, i))
            {
                tmp_opt_id = Menu_GetOptionId(tmp_level_id, Menu_GetCurOptId(tmp_level_id) + i);

                // 绘制目录树
                Draw_DirectoryTree(i, tmp_opt_id);
                // 绘制目录名
                Draw_DirectoryName(i, tmp_opt_id);
                // 对特殊菜单控件的分类渲染
                Draw_Special(i, tmp_opt_id);
            }
        }

        //绘制滚动条
        Draw_RollingStrip(tmp_level_id);

        //显示页码角标
        Draw_PageCornerMark(tmp_level_id);

        //反色高亮被选项
        Draw_ColorHighlight(tmp_level_id);

        //项目滚动处理
        Draw_ItemScroll(tmp_level_id);

        //编码器控制页内选择框滚动选择
        Draw_SelectBox(tmp_level_id);
    
        //更新过渡动画
        Draw_TransitionAnimations(tmp_level_id);
    }
    /** 图标显示 */
    else
    {
        /*  当前菜单使用了图标化的渲染方式 该模式仅支持128*64的屏幕 若宏定义中选择了128*32的屏幕将自动切换为普通文本模式显示菜单
            接受两种尺寸的图标 14x14(推荐) 和 48*48 （不推荐）
            如果为14x14在128*64屏幕中会自动放大到48*48
        */
        //居中显示项目名
        Draw_TextCenter(tmp_level_id);
        Draw_Icon(tmp_level_id);
    }

    /** 按键事件 */
    switch (KeyEvent_Get())
    {
    // 单击或者双击
    case EVT_ONE_CLICK:
    case EVT_DOUBLE_CLICK:
        Menu_DefaultRun(Menu_GetCurLevelId(tmp_level_id),
                        (Menu_GetCurOptId(tmp_level_id) + Menu_GetCScrollBarValue(CScroll_Bar_Scroll)));
        break;

    // 长按 标题跳转
    case EVT_LONG_PRESS:
        Menu_DefaultRun(Menu_GetCurLevelId(tmp_level_id), 0);
        break;
    
    default:
        break;
    }

    Draw_Display();
}